home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / textf.arc / TEXTF.ASM < prev    next >
Assembly Source File  |  1991-04-28  |  14KB  |  446 lines

  1. ;  textf.ASM
  2. ;  TASM routines for use with Unit RLINE.PAS.
  3. ;  Compile with: "TASM RLINE" to create RLINE.OBJ
  4. ;  Modifed to use object by Arthur Zatarain 09/25/89
  5.  
  6. CODE  SEGMENT BYTE PUBLIC
  7.   ASSUME  CS:CODE
  8.   PUBLIC  rfrec@FRead
  9.   public  rfrec@FReadLn
  10.   public  rfrec@FOpen
  11.   public  rfrec@FClose
  12.   public  rfrec@FSeek
  13.  
  14.  
  15. ; set up a STRUCture compatible with the Pascal RFrec Record.
  16. RFrec  STRUC
  17.   Handle  dw ?  ; File handle
  18.   BufStart dw ?  ; Offset Disk buffer
  19.   BufES  dw ?  ; Segment Disk buffer
  20.   BufDI  dw ?  ; Current buffer position = si
  21.   BSize  dw ?  ; Buffer size
  22.   BufCX  dw ?  ; Bytes left to search
  23.   NBufs  dw ?  ; Number of buffers read.
  24.   TotRead dw ?  ; Total bytes last read into buffer.
  25. RFrec  ENDS
  26.  
  27.  
  28. ; Equates for later reference in FRead and FReadLn.
  29. ; These offsets reflect the position after the push BP that always appears
  30. ; at the start of a procedure, not to the actual position on the stack at
  31. ; the time of the call.
  32.  
  33.    RFWordSize EQU  8      ; size of RFrec in words.
  34.    RF         EQU  dword ptr [bp+6]  ; address of RFrec
  35.    RString    EQU  dword ptr [bp+10]  ; address of Return String
  36.    RCh        EQU  dword ptr [bp+10]  ; address of Return Char
  37.  
  38.  
  39.  
  40. ;************* The following PROCs are NOT PUBLIC and are NEAR *************
  41. ;----------------------------------------------------------------------
  42. ; BufMove -
  43. ;  Appends CX number of bytes from ES:DI to RString.
  44. ;  Will not move more than 255 bytes to RString.  If there are more to move,
  45. ;  the rest are thrown away.
  46. ;  Leading ^J's are stripped.
  47. ;
  48. ;  Inputs:  ES:DI = address of bytes to move from.
  49. ;    CX    = # Bytes to move. If CX = 0, length byte is set.
  50. ;    DX    = current length of RString
  51. ;    RString is at [BP+6]
  52. ;
  53. ;  AX Destroyed  BX Unaffected  CX Destroyed DX updated
  54. ;  DS Restored   SI Destroyed   ES Restored  DI Destroyed
  55. ;
  56. BufMove  PROC NEAR
  57.     push ds      ; save RF segment
  58.  
  59.     push es      ; DS = Source segment.
  60.     pop  ds
  61.     mov  si, di    ; SI = Source offset.
  62.  
  63.     jcxz LengthOK    ; Any bytes to move?
  64.  
  65.     cmp  byte ptr [si], 10  ; A ^J?
  66.     jne  NoCtrlJ    ; Not ^J, go on.
  67.     dec  cx      ; Is ^J.
  68.     inc  si
  69.  
  70. NoCtrlJ:  mov  ax, 255    ; ax = max length RString can be.
  71.     cmp  dx, ax    ; RString already at max length?
  72.     je   Bdone    ;  Yes. Get out.
  73.  
  74.     sub  ax, dx    ; AX = 255. DX = length(Rstring)
  75.     cmp  cx, ax    ; are there more than max to move?
  76.     jbe  LengthOK    ; If not, go on.
  77.     mov  cx, ax    ; yes. set cx to ax.
  78.  
  79. LengthOK:  les  di, RString  ; es:di points to RString[0]
  80.     mov  al, dl    ; AL = Length(RString)
  81.     add  al, cl    ; Add bytes to move.
  82.     cld
  83.     stosb      ; Set RString[0].  DI = ofs Rstring[1].
  84.  
  85.     jcxz BDone    ; anything to move now?
  86.     add  di, dx    ; es:di => RString[dl]
  87.     mov  dl, al    ; update length
  88.     shr  cx, 1
  89.     rep  movsw    ; Move cx words.
  90.     rcl  cx, 1
  91.     rep  movsb    ; Move odd byte, if any.
  92.  
  93. BDone:    pop  ds      ; Restore RF segment.
  94.     mov  ax, [bx].BufES  ; Restore Buffer segment.
  95.     mov  es, ax
  96.     ret
  97. BufMove  ENDP
  98.   
  99. ;----------------------------------------------------------------------
  100. ; Fill disk buffer. Read RF.BSize bytes from file RF.Handle to ES:[BufStart].
  101. ;        On last buffer, last ^Z is stripped.
  102. ;   Inputs:
  103. ;  DS:BX must point to RFrec.
  104. ;  ES must point to Buffer segment. ( RF.BufES )
  105. ;
  106. ;   If Failed, returns carry flag set, reason in AX:
  107. ;  a) if a DOS error occurs, the DOS Error code is returned in ax.
  108. ;  b) if end of file (0 bytes left to read),  AX is set to $FFFF
  109. ;
  110. ;   If Successful, returns carry flag clear and:
  111. ;  a) di points to buffer start.
  112. ;  b) cx = number of bytes read.
  113. ;
  114. ; AX Error code if failed    BX restored    CX = Bytes read  DX restored
  115. ; DS restored   SI destroyed ES unaffected  DI = Buffer start
  116. ;
  117. FillBuf    PROC NEAR
  118.     mov  si, dx    ; save Line length
  119.     mov  cx, [bx].BSize
  120.     mov  dx, [bx].BufStart  ; point ds:DX to offset of buffer.
  121.     mov  di, dx    ; (reset BufDI for later)
  122.     mov  bx, [bx].Handle  ; bx = Handle
  123.     mov  ax, es
  124.     mov  ds,ax    ; set DS:dx
  125.     mov  ah, 3fh    ; DOS read file function.
  126.     int  21h
  127.     mov  dx, si    ; restore Line Length
  128.     lds  bx, RF    ; restore RFrec address
  129.     jc   GetOut    ; BlockRead error?
  130.  
  131.     xchg cx, ax    ; ax = bytes to read. cx = bytes read.
  132.     jcxz EOF    ; if no bytes read, we're done
  133.  
  134.     mov  [bx].TotRead, cx  ; store number bytes read.
  135.     inc  [bx].NBufs    ; update file position
  136.  
  137.     cmp  cx, ax    ; is this last buffer?
  138.     je   GetOut    ; if not, we're done.
  139.  
  140.     mov  si, di    ; else check for ^Z
  141.     add  si, cx    ; use si as index.
  142.     cmp  byte ptr es:[si-1], 26  ; end of buffer a ^Z?
  143.     jne  NoCtrlZ    ; no, go on.
  144.     dec  cx      ; yes. Dec bytes read.
  145.     dec  [bx].TotRead
  146.     jcxz EOF    ; if cx = 0 then EOF
  147.  
  148. NoCtrlZ:  clc      ; Return success.
  149.     jmp short GetOut
  150. EOF:    mov  ax, 0FFFFh    ; set result to EOF
  151.     stc      ; Return failure.
  152. GetOut:    ret
  153. FillBuf    ENDP
  154.  
  155.  
  156. ;************* The following PROCs ARE PUBLIC and FAR *************
  157. ;-------------------------------------------------------------------------
  158. ; Function FOpen(Fn : String;
  159. ;                DBsize : Word;
  160. ;                VAR BufP) : Word;
  161. ;  Returns 0 on success, DOS error on failure.
  162.  
  163.   Fn      EQU  dword ptr [bp+16]  ; address of filename
  164.   DBsize  EQU  word ptr  [bp+14]  ; requested size of buffer
  165.   BufP    EQU  dword ptr [bp+10]  ; Ofs of Buffer
  166.   rfr     equ  dword ptr [bp+6]   ; address of rfrec record
  167.  
  168. rfrec@FOpen    PROC FAR
  169.     push bp
  170.     mov  bp,sp
  171.     push ds      ; save turbo's DS
  172.  
  173.     les  di, RfR    ; es:di points to RFrec.
  174.     mov  si, di    ; save RF offset
  175.     xor  ax, ax    ; fill RFrec fields with 0.
  176.     mov  cx, RFWordSize  ; CX = #words to fill
  177.     rep  stosw
  178.     mov  di, si    ; Restore RF offset
  179.  
  180.     cmp  DBsize, ax    ; Is requested buffer size > 0
  181.     jnz  BSizeOK    ; Yes.
  182.     mov  ax, 12    ; No. Return invalid file access code.
  183.     jmp  short OpenDone
  184.  
  185. BSizeOK:  ; make filename asciiz
  186.     lds  si, Fn    ; point to Fn[0]
  187.     mov  bl, [si]
  188.     xor  bh, bh    ; bx = length(Fn)
  189.     inc  si      ; si = offset of Fn[1]
  190.     mov  [si+bx], al  ; Fn[Length(Fn)+1] := 0.
  191.     mov  dx, si    ; ds:dx => Filename[1]
  192.  
  193.     mov  ax,3d00h    ; ax=3D00, open file, read access
  194.     int  21h
  195.     jc   OpenDone    ; if DOS error, return with code in AX
  196.  
  197.     mov  es:[di].Handle, ax  ; else set RFrec.Handle,
  198.     mov  ax, DBsize    ;  and buffer size,
  199.     mov  es:[di].BSize, ax
  200.     lds  si, BufP    ;  and RF Buffer address.
  201.     mov  es:[di].BufStart, si
  202.                 mov  ax, ds
  203.     mov  es:[di].BufES, ax
  204.     xor  ax,ax    ; and return success.
  205.  
  206. OpenDone:  pop  ds      ; restore Turbo DS
  207.     mov  sp,bp
  208.     pop  bp
  209.     ret  14
  210. rfrec@FOpen    ENDP
  211.  
  212. ;-------------------------------------------------------------------------
  213. ; Procedure FClose;
  214. ;  Closes Handle if BSize > 0 and Handle > 4
  215. ;   frec dword [bp+6]
  216.  
  217. rfrec@FClose    PROC FAR
  218.     push bp
  219.     mov  bp,sp
  220.     les  di,[bp+6]    ; ES:DI points to RFrec
  221.  
  222.     xor  ax,ax    ; AX = 0.
  223.     cmp  es:[di].BSize, ax  ; Had it been opened?
  224.     jz   DoneClose    ; No, get out.
  225.     mov  es:[di].BSize, ax
  226.     mov  es:[di].BufCX, ax
  227.  
  228.     mov  bx, es:[di].Handle  ; BX = RF.Handle
  229.     mov  es:[di].Handle, ax  ; RF.Handle = 0
  230.  
  231.     cmp  bx, 4    ; If attempting to close
  232.     jbe  DoneClose    ;  standard DOS device, DON'T.
  233.     mov  ah,3eh    ; DOS close file function
  234.     int  21h
  235. DoneClose:      mov  sp,bp
  236.     pop  bp
  237.     ret  4
  238. rfrec@FClose    ENDP
  239.  
  240. ;-------------------------------------------------------------------------
  241. ; Function FReadLn(VAR RString : String) : Word;
  242. ;
  243. ;      rstring   dword [pb+10]
  244. ;      rfrec     dword [bp+6]
  245. ; If successful:
  246. ;  Returns 0.
  247. ;  RString = string read.
  248. ; If failed:
  249. ;  Returns either DOS error code
  250. ;  or $FFFF if EOF.
  251. ;
  252. ; Calls: FillBuf, BufMove.
  253.  
  254. rfrec@FReadLn       PROC FAR
  255.     cld      ; forward string operations.
  256.     push bp      ; set up pascal stack frame.
  257.     mov  bp,sp
  258.     push ds      ; save turbo's DS
  259.  
  260.     xor  dx, dx    ; dx = line length
  261.     mov  cx, dx    ; cx = 0.
  262.     lds  bx, RF    ; ds:bx points to RFrec
  263.     mov  di, [bx].BufDI  ; DI = Buffer offset.
  264.     mov  ax, [bx].BufES
  265.     mov  es, ax    ; ES:DI points to buffer.
  266.  
  267.     or   cx, [bx].BufCX  ; CX = number bytes left to scan for.
  268.     jnz  Scan    ; if > 0 then scan
  269.     call FillBuf    ;  else fill the buffer.
  270.     jc   Done    ; If error, then get out.
  271.  
  272. Scan:    push di      ; save original buffer position
  273.     push cx      ; save numbytes to scan for
  274.     mov  al, 13    ; scan for CR
  275.     repne scasb
  276.     pop  ax      ; ax = numbytes before scasb
  277.     jz   Found
  278.  
  279.     ; wasn't found. Restore old DI and CX for Bufmove.
  280.     pop  di      ; restore di for BufMove.
  281.     mov  cx, ax    ; restore cx.
  282.     call BufMove    ; move results to RString, and
  283.     call FillBuf    ;  fill the buffer
  284.     jnc  Scan    ; If no error, then keep searching.
  285.  
  286.     ; Either EOF or DOS error occurred.
  287.     cmp  dl, 0    ; Length(RString) = 0?
  288.     je   Done    ; Yes, return FillBuf Error.
  289.           ;  else report no error because some
  290.     xor  ax, ax    ;  chars have already been moved.
  291.     mov  [bx].BufCX, ax  ; Force FillBuf call next time.
  292.     jmp  short done
  293.  
  294. Found:    ; ^M was found.
  295.     mov  [bx].BufDI, di  ; Set up RFrec for next time.
  296.     mov  [bx].BufCX, cx
  297.     pop  di      ; Found so get old DI from stack.
  298.     sub  ax, cx    ; Set up to move to RString.
  299.     dec  ax
  300.     mov  cx, ax
  301.     call BufMove
  302.     xor  ax, ax    ; set return code = 0.
  303.  
  304. Done:    pop  ds      ; Restore everything and return.
  305.     mov  sp,bp
  306.     pop  bp
  307.     ret  8
  308. rfrec@FReadLn  ENDP
  309.  
  310. ;-------------------------------------------------------------------------
  311. ; Function FRead(VAR Ch : Char) : Word;
  312. ; If successful:
  313. ;  Returns 0.
  314. ;  Ch = Character read from file.
  315. ;       All ctrl chars pass, except last ^Z in file, if there is one.
  316. ; If failed:
  317. ;  Returns either DOS error code
  318. ;  or $FFFF if EOF.
  319. ;
  320.  
  321. rfrec@FRead       PROC FAR
  322.     cld      ; all forward string operations.
  323.     push bp      ; set up pascal stack frame.
  324.     mov  bp,sp
  325.     mov  dx, ds    ; save turbo's DS
  326.  
  327.     lds  bx, rf      ; DS:BX points to RFrec
  328.     mov  di, [bx].BufDI  ; DI = Buffer offset.
  329.     mov  cx, [bx].BufCX  ; CX = number of bytes left.
  330.     mov  ax, [bx].BufES
  331.     mov  es, ax    ; ES:DI points to buffer.
  332.  
  333.     jcxz @ReCall
  334.     jmp  short StoreIt
  335. @ReCall:  call FillBuf    ; Fill the buffer
  336.     jc   @Done    ; If error or EOF, then exit.
  337.  
  338. StoreIt:  dec  cx      ; the character is in ES:DI
  339.     mov  [bx].BufCX, cx  ; Set up RFrec for next time.
  340.     mov  al, es:[di]  ; AL = the character.
  341.     inc  di
  342.     mov  [bx].BufDI, di
  343.  
  344. ; set VAR Ch and result.
  345.     les  di, RCh
  346.     stosb
  347.     xor  ax, ax    ; set return code.
  348.  
  349. @Done:    mov  ds, dx    ; Restore everything and return.
  350.     mov  sp,bp
  351.     pop  bp
  352.     ret  8
  353. rfrec@FRead  ENDP
  354.  
  355. ;-------------------------------------------------------------------------
  356. ; Function FSeek(FPo : LongInt) : Word;
  357. ; Seeks to FPo and fills buffer.
  358. ; returns 0 if success
  359. ; else returns dos error code.
  360. ;
  361. ; fpo  word  bp+10
  362. ; self dword pb+6
  363.  
  364. rfrec@FSeek       PROC FAR
  365.     push bp      ; set up pascal stack frame.
  366.     mov  bp,sp
  367.     push ds      ; save turbo's DS
  368.  
  369.     lds  si, RF    ; ds:si points to RFrec
  370.  
  371.     ; set up and divide to find buffer number and offset.
  372.     mov  cx, [si].BSize  ; CX = buffer size.
  373.     jcxz DivZero    ; Avoid divide by zero error
  374.     jmp  short Divide
  375. DivZero:  mov  ax, 200    ; return TP divide by zero error code.
  376.     jmp  short DoneFSeek
  377.  
  378. ;Divide:       ; load AX:DX with FPo
  379. divide:  mov ax, [bp+10]
  380.     mov  dx, [bp+12]
  381.     div  cx      ; calculate the required block number
  382.     inc  ax      ; adjust for one-based NBufs
  383.  
  384. ; BufferNumber is now in AX, Offset in DX
  385.     cmp  [si].NBufs, ax  ; current NBufs = one we're looking for?
  386.     jne  FillerUp    ; no, gotta read it.
  387.     cmp  [si].TotRead, 0  ; yes. Is TotRead in the buffer > 0?
  388.     jz   FillerUp    ; yes. read it from disk.
  389.     jmp  short Filled
  390.  
  391. FillerUp:  ; Move DOS file pointer and fill buffer.
  392.     push dx      ; save file buffer offset to seek to.
  393.     dec  ax      ; adjust BufferNumber for zero base.
  394.     mov  [si].NBufs, ax
  395.     xor  dx, dx    ; prepare to multiply.
  396.     mul  [si].BSize
  397.  
  398.     mov  bx, [si].Handle
  399.     mov  cx, ax    ; load CX:DX with FPo
  400.     xchg cx, dx
  401.     mov  ax, 4200h    ; DOS move file pointer function.
  402.     int  21h
  403.     pop  dx
  404.     jc   DoneFSeek    ; If DOS error, get out.
  405.     ; Successful seek.  Now set up to refill buffer.
  406.     mov  ax, [si].BufES  ; ES = Buffer segment
  407.     mov  es, ax
  408.     mov  bx, si    ; BX = RFrec offset.
  409.     call FillBuf
  410.     mov  si, bx
  411.     jc   DoneFSeek    ; If DOS error, then get out
  412.  
  413. Filled:    ; Buffer is filled.
  414.     ; NBufs is set to proper BufferNumber.
  415.     ; dx = offset in buffer.
  416.  
  417.     ; Adjust RFrec to point to proper position.
  418.     ; set BufCX for next scan.
  419.     mov  ax, [si].TotRead  ; AX = Total bytes in buffer.
  420.     cmp  ax, dx    ; Is dx past end of file?
  421.     ja   InBuffer    ; yes, set BufCX
  422.  
  423.     mov  ax, 100    ; set result to Read Error.
  424.     jmp  short DoneFSeek
  425.  
  426. InBuffer:  sub  ax, dx
  427.     mov  [si].BufCX, ax
  428.  
  429.     ; set BufDI for next scan.
  430.     mov  ax, [si].BufStart  ; AX = Starting offset of buffer.
  431.     add  ax, dx    ; add offset in buffer to seek to.
  432.     mov  [si].BufDI, ax
  433.     xor  ax, ax    ;  return success.
  434.  
  435. DoneFSeek:      pop  ds
  436.     mov  sp,bp
  437.     pop  bp
  438.     ret  8
  439.  
  440. rfrec@FSeek  ENDP
  441.  
  442. ;-------------------------------------------------------------------------
  443.  
  444. CODE  ENDS
  445.   END
  446.